package cn.powertime.evaluation.file.minio;

import cn.powertime.evaluation.DateFormatUtil;
import cn.powertime.evaluation.entity.SysFile;
import cn.powertime.evaluation.exception.FileServerException;
import cn.powertime.evaluation.file.storage.FileInfo;
import cn.powertime.evaluation.file.storage.FileStorage;
import io.minio.MinioClient;
import io.minio.errors.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.multipart.MultipartFile;
import org.xmlpull.v1.XmlPullParserException;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * <p>
 *  Minio实现文件上传下载
 * </p>
 *
 * @author ZYW
 * @version v1.0.0
 * @date 2019-08-23 11:47
 */
@Slf4j
public class MinioFileStorage implements FileStorage {

    private MinioClient minioClient;

    public MinioFileStorage(MinioClient minioClient) {
        this.minioClient = minioClient;
    }

    @Override
    public FileInfo write(MultipartFile file) {
        LocalDateTime now = LocalDateTime.now();
        String bucketName = now.format(DateTimeFormatter.ofPattern(DateFormatUtil.YYYYMMdd));
        try {
            boolean isExist = this.minioClient.bucketExists(bucketName);
            if(!isExist) {
                minioClient.makeBucket(bucketName);
            }

            String origName = file.getOriginalFilename();
            String extName = FilenameUtils.getExtension(origName);
            String newFileName = now.format(DateTimeFormatter.ofPattern(DateFormatUtil.YYYYMMddHHmmssSSS)) + "." + extName;
            long size = file.getSize();

            minioClient.putObject(bucketName, newFileName, file.getInputStream(),file.getSize(),null,null, "application/octet-stream");

            return FileInfo.builder()
                    .name(newFileName)
                    .ext(extName)
                    .origName(origName)
                    .path(bucketName)
                    .size(Long.valueOf(size).intValue())
                    .build();
        } catch (MinioException | NoSuchAlgorithmException | IOException | InvalidKeyException | XmlPullParserException e) {
            log.error("write minio exception: ",e);
            throw new FileServerException("使用minio写文件异常！");
        }
    }

    @Override
    public void read(SysFile file, HttpServletResponse response) {
        final String fileName = file.getName();
        final String bucketName = file.getPath();
        if (StringUtils.isEmpty(fileName) || StringUtils.isEmpty(bucketName)) {
            throw new FileServerException("文件桶或者名称为空！");
        }

        String origName = file.getOrigName();
        InputStream stream = null;
        try {

            // 设置response参数，可以打开下载页面
            response.reset();
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            String filename = URLEncoder.encode(origName, "UTF-8");
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + new String(filename.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));

            stream = minioClient.getObject(bucketName, fileName);

            IOUtils.copy(stream, response.getOutputStream());
        } catch (MinioException | NoSuchAlgorithmException | IOException | InvalidKeyException | XmlPullParserException e) {
            log.error("minio getObject exception:",e);
            throw new FileServerException("文件下载异常！");
        } finally {
            if(stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                    log.error("close stream exception:",e);
                }
            }
        }
    }
}
